//
//  NSData+base64Encoding.m
//  kukushop
//
//  Created by yyt on 13-8-28.
//  Copyright (c) 2013年 yyt. All rights reserved.
//

#import "NSData+base64Encoding.h"
static const char encodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@implementation NSData(base64Encoding)



+ (id)dataWithBase64EncodedString:(NSString *)string {
     if (string == nil)
          [NSException raise:NSInvalidArgumentException format:@""];
     
     if ([string length] == 0)
          return [NSData data];
     
     static char *decodingTable = NULL;
     
     if (decodingTable == NULL) {
          decodingTable = malloc(256);
          if (decodingTable == NULL)
               return nil;
          memset(decodingTable, CHAR_MAX, 256);
          NSUInteger i;
          for (i = 0; i < 64; i++)
               decodingTable[(short)encodingTable[i]] = i;
     }
     
     const char *characters = [string cStringUsingEncoding:NSASCIIStringEncoding];
     if (characters == NULL)
          return nil;
     char *bytes = malloc((([string length] + 3) / 4) * 3);
     if (bytes == NULL)
          return nil;
     
     NSUInteger length = 0;
     NSUInteger i = 0;
     
     while (YES) {
          char buffer[4];
          short bufferLength;
          for (bufferLength = 0; bufferLength < 4; i++) {
               if (characters[i] == '\0')
                    break;
               if (isspace(characters[i]) || characters[i] == '=')
                    continue;
               buffer[bufferLength] = decodingTable[(short)characters[i]];
               if (buffer[bufferLength++] == CHAR_MAX) {
                    free(bytes);
                    return nil;
               }
          }
          
          if (bufferLength == 0)
               break;
          if (bufferLength == 1) {
               free(bytes);
               return nil;
          }
          
          bytes[length++] = (buffer[0] << 2) | (buffer[1] >> 4);
          if (bufferLength > 2)
               bytes[length++] = (buffer[1] << 4) | (buffer[2] >> 2);
          if (bufferLength > 3)
               bytes[length++] = (buffer[2] << 6) | buffer[3];
     }
     
     realloc(bytes, length);
     return [NSData dataWithBytesNoCopy:bytes length:length];
}

- (NSString *)base64Encoding {
     if ([self length] == 0)
          return @"";
     
     char *characters = malloc((([self length] + 2) / 3) * 4);
     if (characters == NULL)
          return nil;
     
     NSUInteger length = 0;
     NSUInteger i = 0;
     
     while (i < [self length]) {
          char buffer[3] = {0,0,0};
          short bufferLength = 0;
          while (bufferLength < 3 && i < [self length])
               buffer[bufferLength++] = ((char *)[self bytes])[i++];
          characters[length++] = encodingTable[(buffer[0] & 0xFC) >> 2];
          characters[length++] = encodingTable[((buffer[0] & 0x03) << 4) | ((buffer[1] & 0xF0) >> 4)];
          if (bufferLength > 1)
               characters[length++] = encodingTable[((buffer[1] & 0x0F) << 2) | ((buffer[2] & 0xC0) >> 6)];
          else characters[length++] = '=';
          if (bufferLength > 2)
               characters[length++] = encodingTable[buffer[2] & 0x3F];
          else characters[length++] = '=';
     }
     
     return [[NSString alloc] initWithBytesNoCopy:characters length:length encoding:NSASCIIStringEncoding freeWhenDone:YES];
}

+ (id)dataWithBase64EncodedWithSafeUrlString:(NSString *)string
{
    NSString *dataString=[string stringByReplacingOccurrencesOfString:@"-" withString:@"+"];
    dataString=[dataString stringByReplacingOccurrencesOfString:@"_" withString:@"/"];
    NSUInteger mod4=dataString.length%4;
    dataString=[dataString stringByAppendingString: [@"====" substringToIndex:mod4]]  ;
    NSData *data=[NSData dataWithBase64EncodedString:dataString];
    return data;
}
- (NSString *)base64EncodingWithSafeUrl{
    NSString *dataString=[self base64Encoding];
    dataString=[dataString stringByReplacingOccurrencesOfString:@"+" withString:@"-"];
    dataString=[dataString stringByReplacingOccurrencesOfString:@"/" withString:@"_"];
    dataString=[dataString stringByReplacingOccurrencesOfString:@"=" withString:@""];
    return dataString;
}


@end
